/**
* 版权所有:版权所有(C) 2020，卓信科技
* 系统名称:FOL-财务管理系统
* 文件名称:CharUtil.java
* 模块名称:TODO(这里请补充模块名称)
* 创建日期:2020年5月19日
* 作        者:baisong
* 内容摘要:TODO(对字符和字符序列操作的工具类。包括<code>char[]</code> - <code>byte[]</code>的转换)
*/
package com.zx.emanage.util.gen;

import java.io.UnsupportedEncodingException;

/**
 * 类  名  称:CharUtil
 * 内容摘要:TODO(对字符和字符序列操作的工具类。包括<code>char[]</code> - <code>byte[]</code>的转换)
 * 作        者:baisong
 */
public class CharUtil
{

	// ---------------------------------------------------------------- simple

	/**
	 * 将（有符号）byte转换成（无符号的）char，字节转换成字符
	 */
	public static char toChar(byte b)
	{
		return (char) (b & 0xFF);
	}

	/**
	 * 通过去除字符的高字节位，将字符数组转换成字节数组
	 *
	 */
	public static byte[] toSimpleByteArray(char[] carr)
	{
		byte[] barr = new byte[carr.length];
		// 循环
		for (int i = 0; i < carr.length; i++)
		{
			barr[i] = (byte) carr[i];
		}
		return barr;
	}

	/**
	 * 将字符序列转换成字节数组
	 * 
	 * @see #toSimpleByteArray(char[])
	 */
	public static byte[] toSimpleByteArray(CharSequence charSequence)
	{
		byte[] barr = new byte[charSequence.length()];
		// 循环
		for (int i = 0; i < barr.length; i++)
		{
			barr[i] = (byte) charSequence.charAt(i);
		}
		return barr;
	}

	/**
	 * 将字节数组转换成字符数组
	 */
	public static char[] toSimpleCharArray(byte[] barr)
	{
		char[] carr = new char[barr.length];
		// 循环
		for (int i = 0; i < barr.length; i++)
		{
			carr[i] = (char) (barr[i] & 0xFF);
		}
		return carr;
	}

	// ---------------------------------------------------------------- ascii

	/**
	 * 返回字符的Ascii值
	 */
	public static int toAscii(char c)
	{
		// 判断
		if (c <= 0xFF)
		{
			return c;
		} 
		else
		{
			return 0x3F;
		}
	}

	/**
	 * 将字符数组转换为{@link #toAscii(char) ASCII} 字节数组
	 */
	public static byte[] toAsciiByteArray(char[] carr)
	{
		byte[] barr = new byte[carr.length];
		// 循环
		for (int i = 0; i < carr.length; i++)
		{
			barr[i] = (byte) ((int) (carr[i] <= 0xFF ? carr[i] : 0x3F));
		}
		return barr;
	}

	/**
	 * 将字符序列转换成ASCII字节数组
	 */
	public static byte[] toAsciiByteArray(CharSequence charSequence)
	{
		byte[] barr = new byte[charSequence.length()];
		// 循环
		for (int i = 0; i < barr.length; i++)
		{
			char c = charSequence.charAt(i);
			barr[i] = (byte) ((int) (c <= 0xFF ? c : 0x3F));
		}
		return barr;
	}

	// ---------------------------------------------------------------- raw
	// arrays

	/**
	 * 通过将每个字符用两个字节替换的方式，将字符数组转换为字节数组
	 */
	public static byte[] toRawByteArray(char[] carr)
	{
		byte[] barr = new byte[carr.length << 1];
		// 循环
		for (int i = 0, bpos = 0; i < carr.length; i++)
		{
			char c = carr[i];
			barr[bpos++] = (byte) ((c & 0xFF00) >> 8);
			barr[bpos++] = (byte) (c & 0x00FF);
		}
		return barr;
	}

	/**
	 * 
	 * 方法名称: toRawCharArray 内容摘要: TODO(这里详细描述这个方法的作用)
	 * 
	 * @param barr
	 * @return
	 *
	 * @author: Baisong
	 * @time:2020年8月25日 下午1:07:06
	 */
	public static char[] toRawCharArray(byte[] barr)
	{
		int carrLen = barr.length >> 1;
		// 判断
		if (carrLen << 1 < barr.length)
		{
			carrLen++;
		}
		char[] carr = new char[carrLen];
		int i = 0, j = 0;
		// 循环
		while (i < barr.length)
		{
			char c = (char) (barr[i] << 8);
			i++;
			// 循环
			if (i != barr.length)
			{
				c += barr[i] & 0xFF;
				i++;
			}
			carr[j++] = c;
		}
		return carr;
	}

	// ---------------------------------------------------------------- encoding

	/**
	 * 将字符数组按默认的UTF-8编码转换成字节数组
	 * 
	 * @param char[] carr，需要转换的字符数组
	 * @return byte[] 按UTF-8编码转换成字节数组
	 */
	public static byte[] toByteArray(char[] carr)
			throws UnsupportedEncodingException
	{
		return new String(carr).getBytes("UTF-8");
	}

	/**
	 * 按指定的编码方式，将字符数组转换为字节数组
	 * 
	 * @param char[] carr，需要转换的字符数组
	 * @param String charset，给定的编码方式
	 * @return byte[] 按指定编码转换后的字节数组
	 */
	public static byte[] toByteArray(char[] carr, String charset)
			throws UnsupportedEncodingException
	{
		return new String(carr).getBytes(charset);
	}

	/**
	 * 按默认的UTF-8编码，将字节数组转换为字符数组
	 * 
	 * @param byte[] barr，需要转换字节数组
	 * @return char[] 转换后的字符数组
	 */
	public static char[] toCharArray(byte[] barr)
			throws UnsupportedEncodingException
	{
		return new String(barr, "UTF-8").toCharArray();
	}

	/**
	 * 按给定编码，将字节数组转换为字符数组。
	 * 
	 * @param byte[] barr，需要转换的字节数组
	 * @param String charset，指定的编码方式
	 * @return char[] 按指定编码转换后的字符数组
	 */
	public static char[] toCharArray(byte[] barr, String charset)
			throws UnsupportedEncodingException
	{
		return new String(barr, charset).toCharArray();
	}

	// ---------------------------------------------------------------- find

	/**
	 * 检查字符数组中是否含有给定的字符
	 * 
	 * @param char c，字符
	 * @param char[] match，需要检查的字符数组
	 * @return <code>true</code> 如果字符数组含有给定的字符
	 */
	public static boolean equalsOne(char c, char[] match)
	{
		// 循环
		for (char aMatch : match)
		{
			// 循环
			if (c == aMatch)
			{
				return true;
			}
		}
		return false;
	}

	/**
	 * 查找source中从index开始的字符，在match数组中第一个出现的下标。
	 * 
	 * @param char[] source，源数组
	 * @param int index，原数组中取字符的下标
	 * @param char[] match，需要检查的字符数组
	 * @return 返回source中从index开始在match中第一个出现的下标，没有返回-1
	 */
	public static int findFirstEqual(char[] source, int index, char[] match)
	{
		// 循环
		for (int i = index; i < source.length; i++)
		{
			// 循环
			if (equalsOne(source[i], match) == true)
			{
				return i;
			}
		}
		return -1;
	}

	/**
	 * 查找源数组中从index开始，第一个和match字符相同的字符下标。
	 * 
	 * @param char[] source，源字符数组
	 * @param int index，源数组开始检查的下标
	 * @param char match，比较的字符
	 * @return 源数组中第index开始的字符中，第一个和match相同字符下标。没有返回-1
	 */
	public static int findFirstEqual(char[] source, int index, char match)
	{
		// 循环
		for (int i = index; i < source.length; i++)
		{
			// 循环
			if (source[i] == match)
			{
				return i;
			}
		}
		return -1;
	}

	/**
	 * 查找给定位置开始的两个数组中第一个不同的字符下标。
	 * 
	 * @param char[] source，源字符数组
	 * @param int index，源字符数组下标
	 * @param char[] match，需要比较字符数组
	 * @return 查找源字符数组中字符与match中第一个不同字符的下标，如果没有返回-1
	 */
	public static int findFirstDiff(char[] source, int index, char[] match)
	{
		// 循环
		for (int i = index; i < source.length; i++)
		{
			// 循环
			if (equalsOne(source[i], match) == false)
			{
				return i;
			}
		}
		return -1;
	}

	/**
	 * 查找源数组中从index开始的第一个与给定字符不同的字符的下标。
	 * 
	 * @param char[] source，源字符数组
	 * @param int index，查找开始的下标
	 * @param char match，比较的字符
	 * @return 源数组从index开始第一个与给定match不同的字符下标，没有返回-1
	 */
	public static int findFirstDiff(char[] source, int index, char match)
	{
		// 循环
		for (int i = index; i < source.length; i++)
		{
			// 判断
			if (source[i] != match)
			{
				return i;
			}
		}
		return -1;
	}

	// ---------------------------------------------------------------- is

	/**
	 * 判断字符是否是空格
	 */
	public static boolean isWhitespace(char c)
	{
		return c <= ' ';
	}

	/**
	 * 判断是否是小写字母
	 */
	public static boolean isLowercaseLetter(char c)
	{
		return (c >= 'a') && (c <= 'z');
	}

	/**
	 * 判断是否是大写字母
	 */
	public static boolean isUppercaseLetter(char c)
	{
		return (c >= 'A') && (c <= 'Z');
	}
	/**
	 * 判断是否是字母
	 */
	public static boolean isLetter(char c)
	{
		return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));
	}
	/**
	 * 判断是否是数字
	 */
	public static boolean isDigit(char c)
	{
		return (c >= '0') && (c <= '9');
	}
	/**
	 * 判断是否是字母或者数字
	 */
	public static boolean isLetterOrDigit(char c)
	{
		return isDigit(c) || isLetter(c);
	}
	/**
	 * 判断是否是字母或者数字或者下划线
	 */
	public static boolean isWordChar(char c)
	{
		return isDigit(c) || isLetter(c) || (c == '_');
	}
	/**
	 * 判断是否是property名字中可以使用的字符
	 */
	public static boolean isPropertyNameChar(char c)
	{
		return isDigit(c) || isLetter(c) || (c == '_') || (c == '.')
				|| (c == '[') || (c == ']');
	}

	// ----------------------------------------------------------------
	// conversions

	/**
	 * 将ASCII字符转换成大写
	 */
	public static char toUpperAscii(char c)
	{
		// 判断
		if (isLowercaseLetter(c))
		{
			c -= (char) 0x20;
		}
		return c;
	}

	/**
	 * 将ASCII字符转换成小写
	 */
	public static char toLowerAscii(char c)
	{
		// 判断
		if (isUppercaseLetter(c))
		{
			c += (char) 0x20;
		}
		return c;
	}

}
